package com.idea.common.profiler;

/**
 * 用来测试并统计线程执行时间的工具
 * 
 * @author xumin
 * @since 2012/03/21
 */
public final class Profiler {
	private static final ThreadLocal<Entry> entryStack = new ThreadLocal<Entry>();

	/**
	 * 开始计时。
	 */
	public static void start() {
		start((String) null);
	}

	/**
	 * 开始计时。
	 * 
	 * @param message
	 *            第一个entry的信息
	 */
	public static void start(String message) {
		entryStack.set(new Entry(message, null, null));
	}

	/**
	 * 开始计时。
	 * 
	 * @param message
	 *            第一个entry的信息
	 */
	public static void start(Message message) {
		entryStack.set(new Entry(message, null, null));
	}

	/**
	 * 清除计时器。
	 * <p>
	 * 清除以后必须再次调用<code>start</code>方可重新计时。
	 * </p>
	 */
	public static void reset() {
		entryStack.set(null);
	}

	/**
	 * 开始一个新的entry，并计时。
	 * 
	 * @param message
	 *            新entry的信息
	 */
	public static void enter(String message) {
		Entry currentEntry = getCurrentEntry();

		if (currentEntry != null) {
			currentEntry.enterSubEntry(message);
		}
	}

	/**
	 * 开始一个新的entry，并计时。
	 * 
	 * @param message
	 *            新entry的信息
	 */
	public static void enter(Message message) {
		Entry currentEntry = getCurrentEntry();

		if (currentEntry != null) {
			currentEntry.enterSubEntry(message);
		}
	}

	/**
	 * 结束最近的一个entry，记录结束时间。
	 */
	public static void release() {
		Entry currentEntry = getCurrentEntry();

		if (currentEntry != null) {
			currentEntry.release();
		}
	}

	/**
	 * 取得耗费的总时间。
	 * 
	 * @return 耗费的总时间，如果未开始计时，则返回<code>-1</code>
	 */
	public static long getDuration() {
		Entry entry = (Entry) entryStack.get();

		if (entry != null) {
			return entry.getDuration();
		} else {
			return -1;
		}
	}

	/**
	 * 列出所有的entry。
	 * 
	 * @return 列出所有entry，并统计各自所占用的时间
	 */
	public static String dump() {
		return dump("", "");
	}

	/**
	 * 列出所有的entry。
	 * 
	 * @param prefix
	 *            前缀
	 * 
	 * @return 列出所有entry，并统计各自所占用的时间
	 */
	public static String dump(String prefix) {
		return dump(prefix, prefix);
	}

	/**
	 * 列出所有的entry。
	 * 
	 * @param prefix1
	 *            首行前缀
	 * @param prefix2
	 *            后续行前缀
	 * 
	 * @return 列出所有entry，并统计各自所占用的时间
	 */
	public static String dump(String prefix1, String prefix2) {
		Entry entry = (Entry) entryStack.get();

		if (entry != null) {
			return entry.toString(prefix1, prefix2);
		} else {
			return "";
		}
	}

	/**
	 * 取得第一个entry。
	 * 
	 * @return 第一个entry，如果不存在，则返回<code>null</code>
	 */
	public static Entry getEntry() {
		return (Entry) entryStack.get();
	}

	/**
	 * 取得最近的一个entry。
	 * 
	 * @return 最近的一个entry，如果不存在，则返回<code>null</code>
	 */
	private static Entry getCurrentEntry() {
		Entry subEntry = (Entry) entryStack.get();
		Entry entry = null;

		if (subEntry != null) {
			do {
				entry = subEntry;
				subEntry = entry.getUnreleasedEntry();
			} while (subEntry != null);
		}

		return entry;
	}

}
